package com.ecoolex.ying.space.core.manager;

import com.ecoolex.framework.common.enums.ResultCode;
import com.ecoolex.framework.common.pojo.Page;
import com.ecoolex.framework.common.pojo.Pagination;
import com.ecoolex.framework.common.pojo.Sorting;
import com.ecoolex.framework.common.pojo.Sortings;
import com.ecoolex.framework.common.util.BizAssert;
import com.ecoolex.framework.common.util.Check;
import com.ecoolex.framework.common.util.RandomUtil;
import com.ecoolex.ying.space.core.dao.EstateProjectActivityGoodsOrderDAO;
import com.ecoolex.ying.space.entity.EstateProjectActivityCoupon;
import com.ecoolex.ying.space.entity.EstateProjectActivityCouponPackage;
import com.ecoolex.ying.space.entity.EstateProjectActivityGoods;
import com.ecoolex.ying.space.entity.EstateProjectActivityGoodsOrder;
import com.ecoolex.ying.space.entity.EstateProjectActivityGoodsOrder.Column;
import com.ecoolex.ying.space.entity.EstateProjectActivityGoodsOrderExample;
import com.ecoolex.ying.space.entity.EstateProjectActivityGoodsOrderExample.Criteria;
import com.ecoolex.ying.space.enums.EstateProjectActivityCouponPackageStatus;
import com.ecoolex.ying.space.enums.EstateProjectActivityGoodsOrderStatus;
import com.ecoolex.ying.space.pojo.SubmitEstateProjectActivityGoodsOrderDTO;
import com.ecoolex.ying.space.pojo.SubmitEstateProjectActivityGoodsOrderDetailDTO;

import java.math.BigDecimal;
import java.time.Instant;
import java.util.Date;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class EstateProjectActivityGoodsOrderManager {
	
    @Autowired
    private EstateProjectActivityGoodsOrderDAO dao;
    
    @Autowired
    private EstateProjectActivityGoodsManager goodsManager;
    
    @Autowired
    private EstateProjectActivityCouponPackageManager couponPackageManager;
    
    @Autowired
    private EstateProjectActivityCouponManager couponManager;
    
    @Autowired
    private EstateProjectActivityGoodsOrderDetailManager orderDetailManager;
    
    @Autowired
    private EstateProjectActivityGoodsOrderRefundAuditManager auditManager;
    
    @Transactional
    public EstateProjectActivityGoodsOrder submit(SubmitEstateProjectActivityGoodsOrderDTO submit, String createUser) {
    	EstateProjectActivityGoodsOrder goodsOrder = new EstateProjectActivityGoodsOrder();
		goodsOrder.setOperationUserId(submit.getOperationUserId());
		String orderNo = createOrderNo();
		goodsOrder.setOrderNo(orderNo);
		goodsOrder.setPaymentImage(submit.getPaymentImage());
		goodsOrder.setPaymentTime(Date.from(Instant.now()));
		List<SubmitEstateProjectActivityGoodsOrderDetailDTO> detailList = submit.getDetailList();
		BigDecimal totalPrice = new BigDecimal(0);
		for (SubmitEstateProjectActivityGoodsOrderDetailDTO detailDTO : detailList) {
			EstateProjectActivityGoods estateProjectActivityGoods = goodsManager.getEstateProjectActivityGoods(detailDTO.getActivityGoodsId());
			BizAssert.isTrue(Check.notNull(estateProjectActivityGoods),ResultCode.VERIFY.build(10), "活动商品不存在");
			BigDecimal price = estateProjectActivityGoods.getActivityPrice().multiply(BigDecimal.valueOf(detailDTO.getBuyNumber()));
			totalPrice = totalPrice.add(price);
		}
		goodsOrder.setTotalPrice(totalPrice);
		goodsOrder.setRealPrice(totalPrice);
		if(Check.notNullOrTrimEmpty(submit.getCouponCode())) {
    		EstateProjectActivityCouponPackage couponPackage = couponPackageManager.getEstateProjectActivityCouponPackageByCode(submit.getCouponCode());
    		BizAssert.isTrue(Check.notNull(couponPackage),ResultCode.VERIFY.build(11), "代金券不存在");
    		BizAssert.isTrue(EstateProjectActivityCouponPackageStatus.UNUSED.equal(couponPackage.getStatus()),ResultCode.VERIFY.build(12), "代金券不可用");
    		goodsOrder.setCouponCode(submit.getCouponCode());
    		EstateProjectActivityCoupon activityCoupon = couponManager.getEstateProjectActivityCoupon(couponPackage.getCouponId());
    		BizAssert.isTrue(Check.isGreatThanEqual(totalPrice, activityCoupon.getUsePrice()),ResultCode.VERIFY.build(13), "代金券不符合使用门槛规则");
    		goodsOrder.setRealPrice(totalPrice.subtract(activityCoupon.getFacePrice()));
    		//核销代金券
    		couponPackageManager.used(couponPackage, createUser);
		}
		goodsOrder.setStatus(EstateProjectActivityGoodsOrderStatus.PAID.real());
		goodsOrder.setRemark(submit.getRemark());
		goodsOrder.setDeleted(EstateProjectActivityGoodsOrder.NOT_DELETED);
		goodsOrder.setCreateUser(createUser);
		goodsOrder.setCreateTime(Date.from(Instant.now()));
		goodsOrder.setUpdateUser(createUser);
		goodsOrder.setUpdateTime(Date.from(Instant.now()));
    	dao.insert(goodsOrder);
    	orderDetailManager.add(goodsOrder, detailList, createUser);
    	return goodsOrder;
	}
    
    public String createOrderNo() {
    	String orderNo = RandomUtil.randomInt(18);
    	EstateProjectActivityGoodsOrder order = get(orderNo);
    	if(Check.notNull(order)) {
    		return createOrderNo();
    	}
    	return orderNo;
    }

	public Pagination<EstateProjectActivityGoodsOrder> queryByOperationUserId(Integer status, Integer operationUserId, Page page) {
		EstateProjectActivityGoodsOrderExample example = new EstateProjectActivityGoodsOrderExample();
		Criteria criteria = example.createCriteria();
		if(Check.notNull(status)) {
			criteria.andStatusEqualTo(status);
		}
		criteria.andOperationUserIdEqualTo(operationUserId).andDeletedEqualTo(EstateProjectActivityGoodsOrder.NOT_DELETED);
		example.setOffset(page.getFirstIndex());
		example.setRows(page.getPageSize());
		example.orderBy(Column.createTime.desc());
		return Pagination.create(page, 
			dao.countByExample(example),
			() -> dao.selectByExample(example));
	}

	public EstateProjectActivityGoodsOrder getByOperationUserId(Integer orderId, Integer operationUserId) {
		EstateProjectActivityGoodsOrderExample example = new EstateProjectActivityGoodsOrderExample();
		Criteria criteria = example.createCriteria();
		criteria.andOrderIdEqualTo(orderId).andOperationUserIdEqualTo(operationUserId).andDeletedEqualTo(EstateProjectActivityGoodsOrder.NOT_DELETED);
		return dao.selectOneByExample(example);
	}

	public Pagination<EstateProjectActivityGoodsOrder> query(Integer status, Sorting[] sorts, Page page) {
		EstateProjectActivityGoodsOrderExample example = new EstateProjectActivityGoodsOrderExample();
		Criteria criteria = example.createCriteria();
		if(Check.notNull(status)) {
			criteria.andStatusEqualTo(status);
		}
		criteria.andDeletedEqualTo(EstateProjectActivityGoodsOrder.NOT_DELETED);
		example.setOffset(page.getFirstIndex());
		example.setRows(page.getPageSize());
		example.orderBy(Sortings.builder(sorts).verify(Column::valueOf).toSql());
		return Pagination.create(page, 
			dao.countByExample(example),
			() -> dao.selectByExample(example));
	}

	public EstateProjectActivityGoodsOrder get(Integer orderId) {
		return dao.selectByPrimaryKeyWithLogicalDelete(orderId, EstateProjectActivityGoodsOrder.NOT_DELETED);
	}
	
	public EstateProjectActivityGoodsOrder get(String orderNo) {
		EstateProjectActivityGoodsOrderExample example = new EstateProjectActivityGoodsOrderExample();
		Criteria criteria = example.createCriteria();
		criteria.andOrderNoEqualTo(orderNo).andDeletedEqualTo(EstateProjectActivityGoodsOrder.NOT_DELETED);
		return dao.selectOneByExample(example);
	}

	@Transactional
	public void refundApply(EstateProjectActivityGoodsOrder record,String updateUser) {
		record.setStatus(EstateProjectActivityGoodsOrderStatus.REFUNDING.real());
		record.setUpdateUser(updateUser);
		record.setUpdateTime(Date.from(Instant.now()));
		dao.updateByPrimaryKeySelective(record, Column.status,Column.updateUser,Column.updateTime);
		//提交到退款审核
		auditManager.add(record, updateUser);
	}
	
	public void cancelOrder(EstateProjectActivityGoodsOrder record,String updateUser){
		record.setStatus(EstateProjectActivityGoodsOrderStatus.REFUND.real());
		record.setUpdateUser(updateUser);
		record.setUpdateTime(Date.from(Instant.now()));
		dao.updateByPrimaryKeySelective(record, Column.status,Column.updateUser,Column.updateTime);
	}
	
	public void updateStatus(Integer orderId,Integer status,String updateUser) {
		EstateProjectActivityGoodsOrder goodsOrder = get(orderId);
		goodsOrder.setStatus(status);
		goodsOrder.setUpdateUser(updateUser);
		goodsOrder.setUpdateTime(Date.from(Instant.now()));
		dao.updateByPrimaryKeySelective(goodsOrder, Column.status,Column.updateUser,Column.updateTime);
	}
}